package com.mytinyRPC.protocol.http;


import com.mytinyRPC.Factory.SingletonFactory;
import com.mytinyRPC.framework.URL;
import com.mytinyRPC.framework.autoScan.ReflectUtil;
import com.mytinyRPC.framework.autoScan.annotate.RpcService;
import com.mytinyRPC.framework.autoScan.annotate.RpcServiceScan;
import com.mytinyRPC.protocol.RpcServer;
import com.mytinyRPC.provider.LocalRegister;
import com.mytinyRPC.provider.LocalRegisterImpl;
import com.mytinyRPC.register.ServiceRegistry;
import com.mytinyRPC.register.zookeeperRegister.ZkServiceRegistry;
import org.apache.catalina.*;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.core.StandardEngine;
import org.apache.catalina.core.StandardHost;
import org.apache.catalina.startup.Tomcat;

import java.net.InetSocketAddress;
import java.util.Set;

public class HttpServer implements RpcServer {
    URL url;
    private static LocalRegister localRegister;
    private static ServiceRegistry serviceRegistry;
    static {
        serviceRegistry= SingletonFactory.getInstance(ZkServiceRegistry.class);
        localRegister=SingletonFactory.getInstance(LocalRegisterImpl.class);
    }
    public void scanServices() {
        String mainClassName = ReflectUtil.getStackTrace();
        Class<?> startClass=null;
        try {
            startClass = Class.forName(mainClassName);
            if(!startClass.isAnnotationPresent(RpcServiceScan.class)) {
                System.out.println("启动类缺少 @RpcServiceScan 注解");
                throw new ClassNotFoundException();
            }
        } catch (ClassNotFoundException e) {
            System.out.println("出现未知错误");
        }
        String basePackage = startClass.getAnnotation(RpcServiceScan.class).value();
        if("".equals(basePackage)) {
            basePackage = mainClassName.substring(0, mainClassName.lastIndexOf("."));
        }
        //扫描该包及其子包下所有的有效Class对象
        Set<Class<?>> classSet = ReflectUtil.getClasses(basePackage);
        for(Class<?> clazz : classSet) {
            if(clazz.isAnnotationPresent(RpcService.class)) {
                String serviceName = clazz.getAnnotation(RpcService.class).name();
                Object obj;
                try {
                    obj = clazz.newInstance();
                } catch (InstantiationException | IllegalAccessException e) {
                    System.out.println("创建 " + clazz + " 时有错误发生");
                    continue;
                }
                if("".equals(serviceName)) {
                    Class<?>[] interfaces = clazz.getInterfaces();
                    for (Class<?> oneInterface: interfaces){
                        publishService(obj, oneInterface.getCanonicalName());
                    }
                } else {
                    publishService(obj, serviceName);
                }
            }
        }
    }

    public <T> void publishService(T service, String serviceName) {
        localRegister.regist(serviceName,service.getClass());

        serviceRegistry.registerService(serviceName, url);
    }
    /***
     * @Author HP
     * @Description //TODO 启动tomcat服务器
     * @Name start
     * @Param [hostName, port]
     * @return void
     **/
    public void start(URL url){
        this.url=url;
        //embed tomcat
        Tomcat tomcat=new Tomcat();

        Server server = tomcat.getServer();
        Service rpcService = server.findService("Tomcat");
        Connector connector = new Connector();
        connector.setPort(url.getPort());
        Engine engine = new StandardEngine();
        engine.setDefaultHost(url.getHostname());

        Host host = new StandardHost();
        host.setName(url.getHostname());
        //设置上下文
        String contextPath="";
        Context context = new StandardContext();
        context.setPath(contextPath);
        context.addLifecycleListener(new Tomcat.FixContextListener());

        host.addChild(context);
        engine.addChild(host);

        rpcService.setContainer(engine);
        rpcService.addConnector(connector);
        //设置拦截servlet
        tomcat.addServlet(contextPath,"dispather",new DispatchServlet());
        context.addServletMappingDecoded("/*","dispather");
        try {
            //启动tomcat
            tomcat.start();
            scanServices();
            tomcat.getServer().await();
        } catch (LifecycleException e) {
            e.printStackTrace();
        }

    }
}
